/**
 * chenuu.com
 * 
 * @author  zhaoxu.com@gmail.com
 * @created 2012-11-10
 */
package com.chenuu.integration.httpclient.dropbox;

import java.util.Map;

import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.json.simple.JSONValue;

import com.dropbox.client2.exception.DropboxException;
import com.dropbox.client2.exception.DropboxParseException;

/**
 *
 */
public class DropboxFileInfo {

	private String mimeType = null;
	private long fileSize = -1;
	private String charset = null;
	private DropboxEntry metadata = null;

	// fileSize and metadata are guaranteed to be valid if the constructor
	// doesn't throw an exception.
	public DropboxFileInfo(HttpResponse response) throws DropboxException {
		metadata = parseXDropboxMetadata(response);
		if (metadata == null) {
			throw new DropboxParseException("Error parsing metadata.");
		}

		fileSize = parseFileSize(response, metadata);
		if (fileSize == -1) {
			throw new DropboxParseException("Error determining file size.");
		}

		// Parse mime type and charset.
		Header contentType = response.getFirstHeader("Content-Type");
		if (contentType != null) {
			String contentVal = contentType.getValue();
			if (contentVal != null) {
				String[] splits = contentVal.split(";");
				if (splits.length > 0) {
					mimeType = splits[0].trim();
				}
				if (splits.length > 1) {
					splits = splits[1].split("=");
					if (splits.length > 1) {
						charset = splits[1].trim();
					}
				}
			}
		}
	}

	/**
	 * Parses the JSON in the the 'x-dropbox-metadata' header field of the http
	 * response.
	 * 
	 * @param response
	 *            The http response for the downloaded file.
	 * @return An Entry object based on the metadata JSON. Can be null if
	 *         metadata isn't available.
	 */
	private static DropboxEntry parseXDropboxMetadata(HttpResponse response) {
		if (response == null) {
			return null;
		}

		Header xDropboxMetadataHeader = response.getFirstHeader("X-Dropbox-Metadata");
		if (xDropboxMetadataHeader == null) {
			return null;
		}

		// Returns null if the parsing fails.
		String json = xDropboxMetadataHeader.getValue();
		Object metadata = JSONValue.parse(json);
		if (metadata == null) {
			return null;
		}
		@SuppressWarnings("unchecked")
		Map<String, Object> map = (Map<String, Object>) metadata;
		return new DropboxEntry(map);
	}

	/**
	 * Determines the size of the downloaded file.
	 * 
	 * @param response
	 *            The http response for the file whose size we're interested in.
	 * @param metadata
	 *            The metadata associated with the file. Can be null if
	 *            unavailable.
	 * @return The determined file size. -1 if the size of the file can't be
	 *         determined.
	 */
	private static long parseFileSize(HttpResponse response, DropboxEntry metadata) {
		// Use the response's content-length, if available (negative if
		// unavailable).
		long contentLength = response.getEntity().getContentLength();
		if (contentLength >= 0) {
			return contentLength;
		}

		// Fall back on the metadata, if available.
		if (metadata != null) {
			return metadata.bytes;
		}

		return -1;
	}

	/**
	 * Returns the MIME type of the associated file, or null if it is unknown.
	 */
	public final String getMimeType() {
		return mimeType;
	}

	/**
	 * @deprecated Replaced by {@link #getFileSize()}
	 */
	@Deprecated
	public final long getContentLength() {
		return getFileSize();
	}

	/**
	 * Returns the size of the file in bytes (always >= 0).
	 */
	public final long getFileSize() {
		return fileSize;
	}

	/**
	 * Returns the charset of the associated file, or null if it is unknown.
	 */
	public final String getCharset() {
		return charset;
	}

	/**
	 * Returns the metadata of the associated file (always non-null).
	 */
	public final DropboxEntry getMetadata() {
		return metadata;
	}
}
